home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ARASAN_S.ZIP / BEARING.CPP < prev    next >
C/C++ Source or Header  |  1994-07-31  |  13KB  |  523 lines

  1. // Copyright 1992-3 by Jon Dart.  All Rights Reserved.
  2.  
  3. #include "bearing.h"
  4. #include "util.h"
  5. #ifdef RANGE_CHECK
  6. #include <assert.h>
  7. #endif
  8. #include "beardata.h"
  9.  
  10. const int RankIncr = 8;    // add this to move 1 rank
  11.  
  12. static inline void 
  13. SetSquare(
  14.       const Square sq, Square * squares, unsigned &NumSquares)
  15. {
  16. #ifdef RANGE_CHECK
  17.     assert(sq.OnBoard());
  18.     assert (NumSquares < Bearing::MaxBearSq);
  19. #endif
  20.     squares[NumSquares++] = sq;
  21. }
  22.  
  23. static void
  24. PawnMoves(const Board & board,
  25.       const ColorType side, const Square i,
  26.       Square * squares, unsigned &NumSquares, const Boolean attacks)
  27. {
  28.     Square start, dest, dest2;
  29.     Piece piece;
  30.  
  31.     if (!attacks)
  32.     {
  33.     start = i;
  34.     dest = (Direction[side] > 0) ? i + RankIncr : i - RankIncr;
  35.     if (dest.OnBoard())
  36.     {
  37.          piece = board[dest];
  38.        if (piece.IsEmpty())
  39.        {
  40.         // 1-square pawn advance
  41.  
  42.            SetSquare(dest, squares, NumSquares);
  43.            if (i.Rank(board.Side()) == 2)
  44.            {
  45.            dest2 = (Direction[side] > 0) ?
  46.              dest + RankIncr : dest - RankIncr;
  47.            if (board[dest2].IsEmpty())    // 2-square advance
  48.                SetSquare(dest2, squares, NumSquares);
  49.            }
  50.        }
  51.     }
  52.     }
  53.     // check for possible captures
  54.     if (i.File() != 1)
  55.     {
  56.       dest = (Direction[side] > 0) ? i + (RankIncr - 1) :
  57.       i - (RankIncr + 1);
  58.       if (dest.OnBoard())
  59.       {
  60.         piece = board[dest];
  61.     if (attacks ||
  62.         (!piece.IsEmpty() && (piece.Color() != board.Side())))
  63.         SetSquare(dest, squares, NumSquares);
  64.       }
  65.     }
  66.     if (i.File() != 8)
  67.     {
  68.       dest = (Direction[side] > 0) ? i + (RankIncr + 1) :
  69.       i - (RankIncr - 1);
  70.       if (dest.OnBoard())
  71.       {
  72.         piece = board[dest];
  73.     if (attacks ||
  74.         (!piece.IsEmpty() && (piece.Color() != board.Side())))
  75.         SetSquare(dest, squares, NumSquares);
  76.       }
  77.     }
  78.     Square epsq = board.EnPassantSq(board.OppositeSide());
  79.     if (!epsq.IsInvalid() && !attacks)
  80.     {
  81.     if ((i.File() != 8 && i + 1 == epsq) || 
  82.         (i.File() != 1 && i - 1 == epsq))
  83.     {
  84.         Square dest(epsq + RankIncr * Direction[side]);
  85.         if (board[dest].IsEmpty())
  86.         SetSquare(dest, squares, NumSquares);
  87.     }
  88.     }
  89. }
  90.  
  91. #define RBMoves(board, data, squares, NumSquares) \
  92.     Square i; \
  93.     while ((i = *data) != 255 && board[i].IsEmpty()) \
  94.     { \
  95.        SetSquare(i,squares,NumSquares); \
  96.        ++data; \
  97.     } \
  98.     if (i != 255 && board[i].Color() != side) \
  99.        SetSquare(i,squares,NumSquares) \
  100.  
  101. #define RBAttacks(board, data, squares, NumSquares) \
  102.     Square i; \
  103.     while ((i = *data) != 255 && board[i].IsEmpty()) \
  104.     { \
  105.        SetSquare(i,squares,NumSquares); \
  106.        ++data; \
  107.     } \
  108.     if (i != 255) \
  109.        SetSquare(i,squares,NumSquares) \
  110.  
  111. static void
  112. KnightMoves(
  113.         const Board & board,
  114.         const Square loc,
  115.         Square * squares,
  116.         unsigned &NumSquares,
  117.         const Boolean attacks)
  118. {
  119.     const ColorType side = board[loc].Color();
  120.     const byte *data = KnightSquares[(int)loc];
  121.     int i = 0;
  122.     while (i < 8 && *data != 255)
  123.     {
  124.         ++i;
  125.     Square dest(*data++);
  126.         Piece piece = board[dest];
  127.     if ((piece.IsEmpty() || (attacks || piece.Color() != side)))
  128.         SetSquare(dest, squares, NumSquares);
  129.     }
  130. }
  131.  
  132. static void
  133. KingMoves(
  134.       const Board & board,
  135.       const Square loc,
  136.       Square * squares,
  137.       unsigned &NumSquares,
  138.       const Boolean attacks)
  139. {
  140.     const ColorType side = board[loc].Color();
  141.     const byte *data = KingSquares[(int)loc];
  142.     for (int i = 0; i <8 && *data != 255 ;i++)
  143.     {
  144.     Square dest(*data++);
  145.         Piece piece = board[dest];
  146.     if ((piece.IsEmpty() || (attacks || piece.Color() != side)))
  147.        SetSquare(dest, squares, NumSquares);
  148.     }
  149. }
  150.  
  151. unsigned 
  152. Bearing::BearSq(const Board & board,
  153.         const Square loc, Square * squares)
  154. {
  155.     unsigned NumSquares = 0;
  156.     int j;
  157.  
  158.     const ColorType side = board[loc].Color();
  159.     switch (board[loc].Type())
  160.     {
  161.     case Piece::Empty:
  162.     break;
  163.     case Piece::Pawn:
  164.     PawnMoves(board, side,
  165.           loc, squares, NumSquares, False);
  166.     break;
  167.     case Piece::Knight:
  168.     KnightMoves(board, loc, squares, NumSquares, False);
  169.     break;
  170.     case Piece::Bishop:
  171.     for (j = 0; j < 4; j++)
  172.     {
  173.         const byte *data = BishopSquares[loc] + (j*8);
  174.         RBMoves(board, data, squares, NumSquares);
  175.     }
  176.     break;
  177.     case Piece::Rook:
  178.     for (j = 0; j < 4; j++)
  179.     {
  180.         const byte *data = RookSquares[loc] + (j*8);
  181.         RBMoves(board, data, squares, NumSquares);
  182.     }
  183.     break;
  184.     case Piece::Queen:
  185.     for (j = 0; j < 4; j++)
  186.     {
  187.         const byte *data = BishopSquares[loc] + (j*8);
  188.         RBMoves(board, data, squares, NumSquares);
  189.     }
  190.     for (j = 0; j < 4; j++)
  191.     {
  192.         const byte *data = RookSquares[loc] + (j*8);
  193.         RBMoves(board, data, squares, NumSquares);
  194.     }
  195.     break;
  196.     case Piece::King:
  197.     KingMoves(board, loc, squares, NumSquares, False);
  198.     break;
  199.     case Piece::Invalid:
  200.     break;
  201.     }
  202.     return NumSquares;
  203. }
  204.  
  205. unsigned 
  206. Bearing::Attack(const Board & board,
  207.         const Square loc, const ColorType side,
  208.         Square * squares,
  209.         Boolean indirect)
  210. {
  211. #ifdef RANGE_CHECK
  212.     assert(loc.OnBoard());
  213. #endif
  214.     int index = 0;
  215.     int i, n;
  216.     Square square1, sq;
  217.     Piece my_pawn(Piece::Pawn, side);
  218.     if (side == Black)
  219.     {
  220.     if (board[loc].IsEmpty())
  221.     {
  222.             Square origin(loc-RankIncr);
  223.         if (origin.OnBoard() &&
  224.             board[origin] == my_pawn)
  225.         squares[index++] = origin;
  226.         if (loc.Rank(side) == 4 && board[origin].IsEmpty() &&
  227.         board[origin - RankIncr] == my_pawn)
  228.         squares[index++] = origin - RankIncr;
  229.     } 
  230.     else if (loc.Rank(side) != 1)
  231.     {
  232.         // square is occupied, try pawn captures
  233.         if (loc.File() != 1 &&
  234.             board[loc - (RankIncr+1)] == my_pawn)
  235.         squares[index++] = loc - (RankIncr+1);
  236.         if (loc.File() != 8 &&
  237.             board[loc - (RankIncr-1)] == my_pawn)
  238.         squares[index++] = loc - (RankIncr-1);
  239.     }
  240.     } 
  241.     else
  242.     {
  243.     if (board[loc].IsEmpty())
  244.     {
  245.             Square origin(loc+RankIncr);
  246.         if (origin.OnBoard() &&
  247.             board[origin] == my_pawn)
  248.         squares[index++] = origin;
  249.         if (loc.Rank(side) == 4 && board[origin].IsEmpty() &&
  250.         board[origin + RankIncr] == my_pawn)
  251.         squares[index++] = origin + RankIncr;
  252.     } 
  253.     else if (loc.Rank(side) != 1)
  254.     {
  255.         if (loc.File() != 8 &&
  256.             board[loc + RankIncr+1] == my_pawn)
  257.         squares[index++] = loc + RankIncr + 1;
  258.         if (loc.File() != 1 &&
  259.             board[loc + RankIncr-1] == my_pawn)
  260.         squares[index++] = loc + RankIncr - 1;
  261.     }
  262.     }
  263.     Piece knight(Piece::Knight, side);
  264.     Piece king(Piece::King, side);
  265.     for (i = 0; i < 8; i++)
  266.     {
  267.     sq = KnightSquares[loc][i];
  268.     if (sq == 255)
  269.         break;
  270.     if (board[sq] == knight)
  271.         squares[index++] = sq;
  272.     }
  273.     for (i = 0; i <8; i++)
  274.     {
  275.     sq = KingSquares[loc][i];
  276.     if (sq == 255)
  277.         break;
  278.     if (board[sq] == king)
  279.         squares[index++] = sq;
  280.     }
  281.     n = index;
  282.     int offset;
  283.     Piece bishop(Piece::Bishop, side);
  284.     Piece queen(Piece::Queen, side);
  285.     Piece rook(Piece::Rook, side);
  286.     Boolean found;
  287.     for (i = 0; i < 4; i++)
  288.     {
  289.     square1 = loc;
  290.     found = False;
  291.     offset = 0;
  292.         const byte *data = BishopSquares[loc] + (8*i);
  293.     while (*data != 255)
  294.     {
  295.           Piece piece;
  296.        do
  297.        {
  298.            if (*data == 255) break;
  299.            square1 = *data++;
  300.            piece = board[square1];
  301.        } while (piece.IsEmpty());
  302.        if (piece == bishop || piece == queen)
  303.        {
  304.            found = True;
  305.            ++n;
  306.            squares[index+offset] = square1;
  307.             if (indirect)
  308.                offset += Bearing::Offset;
  309.            else 
  310.                break;
  311.        }
  312.        else
  313.            break;
  314.     }
  315.     if (found)
  316.             ++index;
  317.         data = RookSquares[loc] + (8*i);
  318.     square1 = loc;
  319.     offset = 0;
  320.     found = False;
  321.     for (;;)
  322.     {
  323.        Piece piece;
  324.        do
  325.        {
  326.            if (*data == 255)
  327.               break;
  328.            square1 = *data++;
  329.            piece = board[square1];
  330.        } while (piece.IsEmpty());
  331.        if (piece == rook || piece == queen)
  332.        {
  333.            found = True;
  334.            ++n;
  335.            squares[index+offset] = square1;
  336.             if (indirect)
  337.                offset += Bearing::Offset;
  338.            else 
  339.                break;
  340.        }
  341.        else
  342.            break;
  343.     }
  344.     if (found)
  345.        ++index;
  346.     }
  347.     return n;
  348. }
  349.  
  350. unsigned 
  351. Bearing::Attack_or_Defend(const Board & board, const Square & loc,
  352.               Square * squares)
  353. {
  354.     unsigned NumSquares = 0;
  355.     int j;
  356.  
  357.     switch (board[loc].Type())
  358.     {
  359.     case Piece::Empty:
  360.     break;
  361.     case Piece::Pawn:
  362.     PawnMoves(board, board[loc].Color(),
  363.           loc, squares, NumSquares, True);
  364.     break;
  365.     case Piece::Knight:
  366.     KnightMoves(board, loc, squares, NumSquares, True);
  367.     break;
  368.     case Piece::Bishop:
  369.     for (j = 0; j < 4; j++)
  370.     {
  371.         const byte *data = BishopSquares[loc] + (j*8);
  372.         RBAttacks(board, data, squares, NumSquares);
  373.     }
  374.     break;
  375.     case Piece::Rook:
  376.     for (j = 0; j < 4; j++)
  377.     {
  378.         const byte *data = RookSquares[loc] + (j*8);
  379.         RBAttacks(board, data, squares, NumSquares);
  380.     }
  381.     break;
  382.     case Piece::Queen:
  383.     for (j = 0; j < 4; j++)
  384.     {
  385.         const byte *data = BishopSquares[loc] + (j*8);
  386.         RBAttacks(board, data, squares, NumSquares);
  387.     }
  388.     for (j = 0; j < 4; j++)
  389.     {
  390.         const byte *data = RookSquares[loc] + (j*8);
  391.         RBAttacks(board, data, squares, NumSquares);
  392.     }
  393.     break;
  394.     case Piece::King:
  395.     KingMoves(board, loc, squares, NumSquares, True);
  396.     break;
  397.     case Piece::Invalid:
  398.     break;
  399.     }
  400.     return NumSquares;
  401. }
  402.  
  403. Boolean Bearing::Pinned( const Board &board, const Square loc,
  404.      Piece &PinnedByPiece, 
  405.      Square &PinnedBySquare,
  406.      int &dir)
  407. {
  408.      Piece p = board[loc];
  409.      if (p.IsEmpty() || p.Type() == Piece::King)
  410.         return False;
  411.      const ColorType side = p.Color();
  412.      const ColorType oside = OppositeColor(side);
  413.      // We "cheat" on constness by altering board[loc].  But we will
  414.      // put the original contents back .. honest
  415.      Piece &place = (Piece &)board[loc];
  416.      place = Piece::EmptyPiece(); // imagine me gone
  417.      Square ks(board.KingPos(side));
  418.      int offset = (int)loc - (int)ks;
  419.      int signOfOffset = Util::Sign(offset);
  420.      if (ks.File() == loc.File())  // possible pin on file
  421.      {
  422.         const byte *data
  423.        = (signOfOffset > 0) ? RookSquares[loc] + 8
  424.          : RookSquares[loc];
  425.     Square newsquare;
  426.     Piece attackPiece;
  427.     while (*data != 255)
  428.     {
  429.         newsquare = *data++;
  430.         attackPiece = board[newsquare];
  431.         if (!attackPiece.IsEmpty())
  432.            break;
  433.     }
  434.     if (attackPiece.Color() == oside && (
  435.        (attackPiece.Type() == Piece::Rook) ||
  436.        (attackPiece.Type() == Piece::Queen)))
  437.         {
  438.         place = p; // put piece back
  439.         PinnedBySquare = newsquare;
  440.         PinnedByPiece = attackPiece;
  441.         dir = ((int)newsquare - (int)loc > 0) ? RankIncr : -RankIncr;
  442.         return True;
  443.     }
  444.     }    
  445.     if (ks.Rank(White) == loc.Rank(White))  // possible pin on rank
  446.     {
  447.         const byte *data = (signOfOffset > 0) ?
  448.        RookSquares[loc]+16 : RookSquares[loc]+24;
  449.     Square newsquare;
  450.     Piece attackPiece;
  451.     while (*data != 255)
  452.     {
  453.         newsquare = *data++;
  454.         attackPiece = board[newsquare];
  455.         if (!attackPiece.IsEmpty())
  456.            break;
  457.     }
  458.     if (attackPiece.Color() == oside && (
  459.        (attackPiece.Type() == Piece::Rook) ||
  460.        (attackPiece.Type() == Piece::Queen)))
  461.         {
  462.         place = p; // put piece back
  463.         PinnedBySquare = newsquare;
  464.         PinnedByPiece = attackPiece;
  465.         dir = ((int)newsquare > (int)loc) ? 1 : -1;
  466.         return True;
  467.     }
  468.     }
  469.     if (offset % 9 == 0) // possible diagonal pin
  470.     {
  471.         const byte *data
  472.        = (signOfOffset > 0) ? BishopSquares[loc] + 16
  473.          : BishopSquares[loc] + 8;
  474.     Square newsquare;
  475.     Piece attackPiece;
  476.     while (*data != 255)
  477.     {
  478.         newsquare = *data++;
  479.         attackPiece = board[newsquare];
  480.         if (!attackPiece.IsEmpty())
  481.            break;
  482.     }
  483.     if (attackPiece.Color() == oside && (
  484.        (attackPiece.Type() == Piece::Bishop) ||
  485.        (attackPiece.Type() == Piece::Queen)))
  486.         {
  487.         place = p; // put piece back
  488.         PinnedBySquare = newsquare;
  489.         PinnedByPiece = attackPiece;
  490.         dir = ((int)newsquare > (int)loc) ? 9 : -9;
  491.         return True;
  492.     }
  493.     }
  494.     if (offset % 7 == 0) // possible diagonal pin
  495.     {
  496.         const byte *data
  497.        = (signOfOffset > 0) ? BishopSquares[loc] + 24
  498.          : BishopSquares[loc];
  499.     Square newsquare;
  500.     Piece attackPiece;
  501.     while (*data != 255)
  502.     {
  503.         newsquare = *data++;
  504.         attackPiece = board[newsquare];
  505.         if (!attackPiece.IsEmpty())
  506.            break;
  507.     }
  508.     if (attackPiece.Color() == oside && (
  509.        (attackPiece.Type() == Piece::Bishop) ||
  510.        (attackPiece.Type() == Piece::Queen)))
  511.         {
  512.         place = p; // put piece back
  513.         PinnedBySquare = newsquare;
  514.         PinnedByPiece = attackPiece;
  515.         dir = ((int)newsquare > (int)loc) ? 7 : -7;
  516.         return True;
  517.     }
  518.     }
  519.     place = p;
  520.     return False;
  521. }
  522.  
  523.